// Contient toutes les spécifications de classes nécessaires
// pour représenter l'arbre abstrait
#ifndef ARBRE_H_
#define ARBRE_H_

#include <vector>
#include <iostream>
#include <iomanip>
using namespace std;

#include "Symbole.h"

////////////////////////////////////////////////////////////////////////////////
class Noeud {
// classe abstraite dont dériveront toutes les classes servant à représenter l'arbre abstrait
// Remarque : la classe ne contient aucun constructeur
  public:
    virtual int  getValeur() =0 ; // méthode pure (non implémentée) qui rend la classe abstraite
    virtual void afficher(unsigned short indentation=0) { cout << setw(4*indentation) << " "; }
      // pour afficher un noeud avec un décalage (indentation) proportionnel à son niveau dans l'arbre

    virtual ~Noeud() {} // présence d'un destructeur virtuel conseillée dans les classes abstraites
};

////////////////////////////////////////////////////////////////////////////////
class NoeudSeqInst : public Noeud {
// classe pour représenter un noeud "sequence d'instruction"
// qui a autant de fils que d'instructions dans la séquence
  public:
     NoeudSeqInst();   // construit une séquence d'instruction vide
    ~NoeudSeqInst() {} // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue chaque instruction de la séquence
    void afficher(unsigned short indentation=0); // affiche la séquence d'instructions
    void ajouteInstruction(Noeud* instruction);  // ajoute une instruction à la séquence

  private:
    vector<Noeud *> tabInst; // pour stocker les instructions de la séquence
};

////////////////////////////////////////////////////////////////////////////////
class NoeudAffectation : public Noeud {
// classe pour représenter un noeud "affectation"
// composé de 2 fils : la variable et l'expression qu'on lui affecte
  public:
     NoeudAffectation(Noeud* variable, Noeud* expression); // construit une affectation
    ~NoeudAffectation() {} // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation=0); // affiche l'affectation

  private:
    Noeud* variable;
    Noeud* expression;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudOperateurAdd : public Noeud {
// classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
// et de 2 fils : l'opérande gauche et l'opérande droit
  public:
    NoeudOperateurAdd(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
     // construit une opération binaire : operandeGauche operateur OperandeDroit
   ~NoeudOperateurAdd() {} // à cause du destructeur virtuel de la classe Noeud
  
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation=0); // affiche l'opération

  private:
    Symbole operateur;
    Noeud*  operandeGauche;
    Noeud*  operandeDroit;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudOperateurMult : public Noeud {
// classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
// et de 2 fils : l'opérande gauche et l'opérande droit
  public:
    NoeudOperateurMult(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
     // construit une opération binaire : operandeGauche operateur OperandeDroit
   ~NoeudOperateurMult() {} // à cause du destructeur virtuel de la classe Noeud
   
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation=0); // affiche l'opération

  private:
    Symbole operateur;
    Noeud*  operandeGauche;
    Noeud*  operandeDroit;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudOperateurEt : public Noeud {
// classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
// et de 2 fils : l'opérande gauche et l'opérande droit
  public:
    NoeudOperateurEt(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
     // construit une opération binaire : operandeGauche operateur OperandeDroit
   ~NoeudOperateurEt() {} // à cause du destructeur virtuel de la classe Noeud
   
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation=0); // affiche l'opération

  private:
    Symbole operateur;
    Noeud*  operandeGauche;
    Noeud*  operandeDroit;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudOperateurOu : public Noeud {
// classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
// et de 2 fils : l'opérande gauche et l'opérande droit
  public:
    NoeudOperateurOu(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
     // construit une opération binaire : operandeGauche operateur OperandeDroit
   ~NoeudOperateurOu() {} // à cause du destructeur virtuel de la classe Noeud
   
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation=0); // affiche l'opération

  private:
    Symbole operateur;
    Noeud*  operandeGauche;
    Noeud*  operandeDroit;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudOperateurRel : public Noeud {
// classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
// et de 2 fils : l'opérande gauche et l'opérande droit
  public:
    NoeudOperateurRel(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
     // construit une opération binaire : operandeGauche operateur OperandeDroit
   ~NoeudOperateurRel() {} // à cause du destructeur virtuel de la classe Noeud
   
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation=0); // affiche l'opération

  private:
    Symbole operateur;
    Noeud*  operandeGauche;
    Noeud*  operandeDroit;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudOperateurUnaire : public Noeud {
// classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
// et de 2 fils : l'opérande gauche et l'opérande droit
  public:
    NoeudOperateurUnaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
     // construit une opération binaire : operandeGauche operateur OperandeDroit
   ~NoeudOperateurUnaire() {} // à cause du destructeur virtuel de la classe Noeud
   
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation=0); // affiche l'opération

  private:
    Symbole operateur;
    Noeud*  operandeGauche;
    Noeud*  operandeDroit;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstSi : public Noeud {
// class pour InstSi ! Trop coool
    
  public:
      NoeudInstSi();
      void ajoute (Noeud* cond, Noeud* seq);
      void afficher(unsigned short indentation=0);
      int getValeur();
      
  private:
      vector<Noeud*> VectCond;
      vector<Noeud*> VectSeqInst;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstTq : public Noeud {
// class pour InstTq ! Trop coool
    
  public:
      NoeudInstTq(Noeud* cond, Noeud* seq);
      void afficher(unsigned short indentation=0);
      int getValeur();
      Noeud* getseq();
      Noeud* getcond();
      
  private:
      Noeud* cond;
      Noeud* seq;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstPour : public Noeud {
// class pour InstPour ! Trop coool
    
  public:
      NoeudInstPour(Noeud* affect1, Noeud* cond,Noeud* affect2, Noeud* seq);
      void afficher(unsigned short indentation=0);
      int getValeur();
      
  private:
      Noeud* affect1;
      Noeud* cond;
      Noeud* affect2;
      Noeud* seq;
};


////////////////////////////////////////////////////////////////////////////////
class NoeudInstRepeter : public NoeudInstTq {
// classe pour InstRepeter


  public:
     NoeudInstRepeter(Noeud* cond, Noeud* seq); 
    ~NoeudInstRepeter() {}                            
    int getValeur();                                  
    void afficher(unsigned short indentation=0);      


};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstLire : public Noeud {
// classe pour InstLire

  public:
     NoeudInstLire(Noeud* variable);              
    ~NoeudInstLire() {}                           
     int getValeur();                             
     void afficher(unsigned short indentation=0); 


  private:
   
    Noeud* variable;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstEcrire : public Noeud {
// classe pour InstEcrire

  public:
     NoeudInstEcrire(Noeud* expression);         
    ~NoeudInstEcrire() {}                        
     int getValeur();                             
     void afficher(unsigned short indentation=0); 


  private:
  
    Noeud* expression;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstSwitch: public NoeudInstSi{
    // classe pour InstSwitch
public:
        NoeudInstSwitch(Noeud* variable );
        ~NoeudInstSwitch() {} 
        void afficher(unsigned short indentation = 0);
        void ajoutecond(Noeud* cond);
        void ajouteseq(Noeud* seq);

private:
        Noeud* variable; // variable sur laquelle on effectue le switch
        vector<Noeud*> vCond;
        vector<Noeud*> vSeqInst;
};

#endif /* ARBRE_H_ */
